package com.youboy.wechatapi.utils.wechat;

import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.codehaus.jackson.type.JavaType;

import com.youboy.wechatapi.utils.http.HttpClient;
import com.youboy.wechatapi.utils.json.JacksonMapper;

/**
 * @ProjectName：wechatapi   
 * @author：冉尧（Yvan）
 * @CreateTime：2014年10月29日 下午3:11:53  
 * @Remarks：   微信接口
 */
public class WechatApi {
	
	private static Logger log = Logger.getLogger(WechatApi.class);
	
	/**
	 * Token(令牌)
	 */
	public final static String TOKEN = "youboy"; 
	
	/**
	 * AppID(应用ID)
	 * 正式账号
	 */
	public final static String APPID = "wx38b4f62566498991";
	/**
	 * AppID(应用ID)
	 * 测试账号
	 */
	//public final static String APPID = "wx5d7bb13651414c5d";
	
	/**
	 * AppSecret(应用密钥)
	 * 正式账号
	 */
	public final static String SECRET = "eeaa653b15a13202ae9b3fc868a822b6";

	/**
	 * AppSecret(应用密钥)
	 * 测试账号
	 */
	//public final static String SECRET = "895c6a5a78597802b850b47f67c254ae";

	
	/**
	 * URL(服务器地址)
	 */
	public final static String URL = "http://wechatapi.youboy.com";
	
	//public final static String URL = "http://218.107.11.135";
	
	/**
	 * EncodingAESKey(消息加解密密钥)
	 */
	public final static String ENCODINGAESKEY = "oHBcI9oRvnWH5guL8a5UhE2EXzLzMrxa01qoaIU8BJO ";
	
	
	/**
	 * 获取access_token的接口地址（GET） 限200（次/天）   
	 */
	public final static String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
	
	/**
	 * 上传多媒体文件
	 */
	public final static String MEDIA_UPLOAD_URL = "http://file.api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE";
	
	/**
	 * 下载多媒体文件
	 */
	public final static String MEDIA_GET_URL = "http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID";
	
	/**
	 * 发送客服消息
	 * @access_token 	必 	调用接口凭证
	 */
	public final static String MESSAGE_CUSTOM_SEND_URL = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN";
	
	/**
	 * 模板消息接口
	 */
	public final static String MESSAGE_TEMPLATE_SEND_URL = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN";
	
	/**
	 * 自定义菜单创建接口
	 */
	public final static String MENU_CREATE_URL = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";
	
	/**
	 * 自定义菜单查询接口
	 */
	public final static String MENU_GET_URL = "https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN";
	
	/**
	 * 自定义菜单删除接口
	 */
	public final static String MENU_DELETE_URL = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN";
	
	/**
	 * 获取用户基本信息（包括UnionID机制）
	 * @access_token 	必须 	调用接口凭证
	 * @openid 	必须 	普通用户的标识，对当前公众号唯一
	 * @lang 	否 	返回国家地区语言版本，zh_CN 简体，zh_TW 繁体，en 英语 
	 */
	public final static String USER_INFO_URL = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
	
	/**
	 * 用户同意授权，获取code
	 * @appid 	必 	公众号的唯一标识
	 * @redirect_uri 	必 	授权后重定向的回调链接地址，请使用urlencode对链接进行处理
	 * @response_type 	必 	返回类型，请填写code
	 * @scope 	必 	应用授权作用域，snsapi_base （不弹出授权页面，直接跳转，只能获取用户openid），snsapi_userinfo （弹出授权页面，可通过openid拿到昵称、性别、所在地。并且，即使在未关注的情况下，只要用户授权，也能获取其信息）
	 * @state 	否 	重定向后会带上state参数，开发者可以填写a-zA-Z0-9的参数值
	 * @wechat_redirect 	必 	无论直接打开还是做页面302重定向时候，必须带此参数 (#wechat_redirect)
	 */
	public final static String OAUTH2_AUTHORIZE_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect";
	
	/**
	 * 通过code换取网页授权access_token
	 * @appid 	必 	公众号的唯一标识
	 * @secret 	必 	公众号的appsecret
	 * @code 	必 	填写 OAUTH2_AUTHORIZE_URL 获取的code参数
	 * @grant_type 	必 	填写为authorization_code 
	 */
	public final static String OAUTH2_ACCESSTOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
	
	/**
	 * 刷新access_token（如果需要）
	 * @appid 	必 	公众号的唯一标识
	 * @grant_type 	必	填写为refresh_token
	 * @refresh_token 	必 	填写通过access_token获取到的refresh_token参数 
	 */
	public final static String OAUTH2_REFRESH_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN";
	
	/**
	 * 创建二维码ticket
	 */
	public final static String QRCODE_CREATE_URL = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKEN";
	
	/**
	 * 通过ticket换取二维码
	 */
	public final static String SHOWQRCODE_URL = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=TICKET";
	
	public final static String SHORT_URL = "https://api.weixin.qq.com/cgi-bin/shorturl?access_token=ACCESS_TOKEN";
	
	
	/**
	 * 根据code获取openid
	 * @param code
	 * @return
	 */
	public static String getOpenid(String code){
		if (StringUtils.isBlank(code)) {
			log.info("code is null, can't send request !");
			return null;
		}
		
		String url = WechatApi.OAUTH2_ACCESSTOKEN_URL.replace("APPID", WechatApi.APPID)
				.replace("SECRET", WechatApi.SECRET)
				.replace("CODE", code);

		String httpsRequest = null;
		try {
			httpsRequest = HttpClient.httpsRequest(url, HttpClient.RequestMethod.GET);
		} catch (Exception e) {
			log.error("[code:" + code + "] get openid from wechat by code error !", e);
			return null;
		}
		
		if(StringUtils.isBlank(httpsRequest)){
			log.error("send get opendi fail, the return content is null !");
			return null;
		}
		
		Map<String, Object> tokenMap = null;
		try {
			JavaType type = JacksonMapper.getInstance().getTypeFactory()
					.constructMapType(Map.class, String.class, Object.class);
			tokenMap = JacksonMapper.getInstance().readValue(httpsRequest, type);
		} catch (Exception e) {
			log.error("[code:" + code + "][json:" + httpsRequest + "] get Openid then result convert to map error !", e);
		}

		if (tokenMap == null || tokenMap.size() == 0) {
			log.error("[code:" + code + "][json:" + httpsRequest + "] get openid by code, the resultMap is null !");
			return null;
		}

		Object openid = tokenMap.get("openid");
		
		if( openid == null){
			log.error("[code:" + code + "][json:" + httpsRequest + "] get openid by code tatal , the openid is null !");
			return null;
		}
		log.info("[code:" + code + "] get openid by code success !");
		return openid.toString();
	}
	
	public static String getUserInfo(String openid) throws Exception{
		if(StringUtils.isBlank(openid)){
			log.error("the openid is null, getUserInfo by openid fatal !");
			return null;
		}
		
		String accessToken = WeixinUtil.getAccessToken(WechatApi.APPID, WechatApi.SECRET).getToken();
		String url = WechatApi.USER_INFO_URL.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openid);
		String httpsRequest = HttpClient.httpsRequest(url, HttpClient.RequestMethod.GET);
		
		return httpsRequest;
	}
	
	public static void main(String[] args) {
		try {
			System.out.println(getUserInfo("ouP3htzNOPVgX8ZNs4oTo1QKg6sw"));
		} catch (Exception e) {
			
			e.printStackTrace();
		}
	}

}

